package main

import "fmt"

// 结构体
// 对象
type rect struct {
	width, height int
}

// 作用于特定类型的函数,特定类型变量称为接收者(receiver).类比js中的this
/*
	func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {}
	建议:
	1. 接收者变量：接收者中的参数变量名在命名时，官方建议使用接收者类型名的第一个小写字母
	2. 接收者类型：接收者类型和参数类似，可以是指针类型和非指针类型
	3. 方法名、参数列表、返回参数：具体格式与函数定义相同
	区别函数:
	函数不属于任何类型,方法属于特定类型
*/
// 结构体函数
// 对象方法
// 1. 指针类型的接收者: 由一个结构体的指针组成
// 由于指针的特性，调用方法时修改接收者指针的任意成员变量，在方法结束后，修改都是有效的
// 2. 值类型的接收者: 当方法作用于值类型接收者时，Go语言会在代码运行时将接收者的值复制一份。
// 在值类型接收者的方法中可以获取接收者的成员值，但修改操作只是针对副本，无法修改接收者变量本身
/*
	什么时候使用指针接受者
	1.需要修改接收者中的值
  2.接收者是拷贝代价比较大的大对象
  3.保证一致性，如果有某个方法使用了指针接收者，那么其他的方法也应该使用指针接收者
*/
func (r *rect) area() int {
	return r.width * r.height
}

func (r rect) perim() int {
	r.width = 30
	return 2*r.width + 2*r.height
}

func main() {
	r := rect{width: 10, height: 20}
	fmt.Println("area:", r.area())
	fmt.Println("area:", r.perim())
	rs := &r
	fmt.Println("area:", rs.area())
	fmt.Println("area:", rs.perim())
}

